package tiasw;

/**
 * Title:        Turnout In a Small World
 * Description:  Program to study how neighborhood influence propagates turnout behavior.
 * Copyright:    Copyright (c) 2002
 * Company:      Harvard University
 * @author James Fowler
 * @version 1.0
 */

import uchicago.src.sim.util.SimUtilities;
import uchicago.src.sim.engine.*;
import uchicago.src.sim.analysis.*;
import java.text.*;
import java.util.*;

public class ModelBatch extends Model {

// Batch variables
DataRecorder recorder;  // Repast's mechanism for data recording.


/////////////////////////////////////////////////////////////////////////

  // The batch module's default variable settings have to be defined.
  // Note that all the other default settings are defined in Model.setup().
  // Also note that all settings here can be overridden by the parameter file.
  public void setup() {
    // Initializing the original model first
    super.setup();

    // Generate random parameter combinations
    // we use Math.random here to avoid influencing the Colt random number
    // generator used to keep realizations of random variables constant
    // when ego votes and doesn't vote
    numCitizens = (int)(Math.random()*99000.0)+1000;
    numDiscussions = (int)(Math.random()*20.0+1.0);
    aveDegree=(int)(Math.random()*9.0+2.0)*2;  // must be an even number
    rewireRate=Math.random()*.19+0.01;
    imitationRate=Math.random()*0.05;

    // there is an exponential relationship between corr and prefCorr,
    // which would mean we sample more often from higher
    // preference correlations if we used a simple linear search.  We therefore
    // wieght the sample downward by choosing a corr and then squaring it
    corr=Math.pow(Math.random()*Math.sqrt(0.5),2.0)+0.5;  // 0=no preference correlation, 1= most correlation

    // Specify the parameters to be manipulated by Repast's parameter
    // mechanism (i.e. set from the parameter file).
    params = new String[] { "numCitizens", "aveDegree", "rewireRate","corr"
    ,"imitationRate","numDiscussions","rngSeed"};

  }
/////////////////////////////////////////////////////////////////////////

  // The method to build the Model's internals //////////////////////////
  // Here we build the model instrumentation after the model itself has
  // been built. We make sure that the data recorder is initialized.
  public void buildModel() {
    // Build the original model first
    super.buildModel();

    // Format the current time to append to filename
   //  SimpleDateFormat formatter = new SimpleDateFormat ("yyMMddhhmmss");
     SimpleDateFormat formatter = new SimpleDateFormat ("yyMMdd");
     Date currentTime = new Date();
     String fileName = "./data1"+formatter.format(currentTime)+".csv";

    // Build the Batch-part
    // Create the DataRecorder object and specify the name of the output file.
    // (For details see Repast's appropriate "How to" document.)
    recorder = new DataRecorder(fileName, this);

    // We create data columns in our output file.
    // The string that appears as the last arguments refers to a method name
    // that is defined below.
    recorder.createNumericDataSource("numCitizens", this, "getNumCitizens");
    recorder.createNumericDataSource("aveDegree", this, "getAveDegree");
    recorder.createNumericDataSource("corr", this, "getCorr");
    recorder.createNumericDataSource("imitationRate", this, "getImitationRate");
    recorder.createNumericDataSource("numDiscussions", this, "getNumDiscussions");
    recorder.createNumericDataSource("rewireRate", this, "getRewireRate");

//    recorder.createNumericDataSource("Ego Clustering Coefficient", this, "getEgoClustCoef");
    recorder.createNumericDataSource("Average Path Length", this, "getAvePathLength");
    recorder.createNumericDataSource("Clustering Coefficient", this, "getClustCoef");
    recorder.createNumericDataSource("Preference Correlation", this, "getPrefCorr");
    recorder.createNumericDataSource("Left Total", this, "getLeftTotal");
    recorder.createNumericDataSource("Right Total", this, "getRightTotal");
    recorder.createNumericDataSource("Left Change", this, "getDLeft");
    recorder.createNumericDataSource("Right Change", this, "getDRight");
//    recorder.createNumericDataSource("Net Favorable Change", this, "getNet");
    recorder.createNumericDataSource("Net Favorable Change", this, "getNetTotal");

  }

/////////////////////////////////////////////////////////////////////////
//  Iterated methods ////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////

  // We suppress the original model's reportResults() and reportElection() methods by
  // overriding them.  We do so in order to prevent excessive output on the screen.
  public void reportResults() {
  }

  public void reportElection() {
  }

/////////////////////////////////////////////////////////////////////////
// We set the recorder to record data at the end of election
// if we are interested in ego data
  public void step() {
    super.step();

    // Record the results into the DataRecorder...
//    recorder.record();


  }

/////////////////////////////////////////////////////////////////////////

// We set the recorder to write data at the end of each simulation if we
// are interested in expected values
  public void atEnd() {

    // Record the results into the DataRecorder...
    recorder.record();
    // ... and write it into the file right away.
    recorder.writeToFile();

  }

/////////////////////////////////////////////////////////////////////////
// RePast Parameter Panel Methods ///////////////////////////////////////
/////////////////////////////////////////////////////////////////////////

  // In the following we provide get/set methods for all the parameters
  // we listed in params (see the setup() method)

  public double getNumCitizens() {
    return (double)numCitizens;
  }

  public void setNumCitizens(int n) {
    numCitizens = n;
  }

  public double getNumDiscussions() {
    return (double)numDiscussions;
  }

  public void setNumDiscussions(int n) {
    numDiscussions = n;
  }

  public double getCorr() {
    return corr;
  }

  public void setCorr(double c) {
    corr = c;
  }

  public double getAveDegree() {
    return (double) aveDegree;
  }

  public void setAveDegree(int d) {
    aveDegree = d;
  }

  public double getRewireRate() {
    return rewireRate;
  }

  public void setRewireRate(double r) {
    rewireRate = r;
  }

  public double getImitationRate() {
    return imitationRate;
  }

  public void setImitationRate(double r) {
    imitationRate = r;
  }

  public double getAvePathLength() {
    return avePathLength;
  }

  public double getClustCoef() {
    return clustCoef;
  }

  public double getEgoClustCoef() {
    return egoClustCoef;
  }

  public double getPrefCorr() {
    return prefCorr;
  }

  public double getLeftTotal() {
    return (double)leftTotal;
  }

  public double getRightTotal() {
    return (double)rightTotal;
  }

  public double getDLeft() {
    return (double)dLeft;
  }

  public double getDRight() {
    return (double)dRight;
  }

  public double getNet() {
    return (double)net;
  }

  public double getNetTotal() {
    return (double)netTotal/(double)numEgoSample;
  }


/////////////////////////////////////////////////////////////////////////
// Creating and starting the model /////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
  public static void main(String[] args) {
    SimInit init = new SimInit();
    // We MUST create a ModelBatch object instead of an instance of Model
    // or that of a ModelGUI, in order to get the Batch functionality.
    Model m = new ModelBatch();
    // The second parameter specifies the name of the parameter file, while
    // the third one declares that the model is to be run in batch-mode.
    init.loadModel(m, "params.txt", true);
  }
}